package com.wdb.common.configurer.httpclient;

import com.wdb.common.util.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class HttpHandlerSupport implements HttpHandler {
    private HttpClient httpClient;

    private RequestConfig requestConfig;

    @Override
    public String get(String uri) {
        try {
            HttpGet get = new HttpGet(uri);

            get.setConfig(requestConfig);

            HttpResponse response = httpClient.execute(get);

            StatusLine line = response.getStatusLine();

            if (Objects.nonNull(line) && Objects.equals(HttpStatus.SC_OK, line.getStatusCode())) {
                return EntityUtils.toString(response.getEntity(), "UTF-8");
            }

            throw new RuntimeException(" HTTP HANDLE FAILED ");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    public String get(String uri, Map<String, Object> parameters) {
        try {
            URIBuilder builder = new URIBuilder(uri);

            if (Objects.nonNull(parameters)) {
                parameters.forEach((key, value) -> {
                    if (Objects.nonNull(value)) {
                        builder.setParameter(key, value.toString());
                    }
                });
            }

            String str = builder.build().toString();

            return get(str);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    public String get(String uri, Map<String, Object> parameters, Map<String, String> headers) {
        try {
            URIBuilder builder = new URIBuilder(uri);

            if (Objects.nonNull(parameters)) {
                parameters.forEach((key, value) -> {
                    if (Objects.nonNull(value)) {
                        builder.setParameter(key, value.toString());
                    }
                });
            }

            String str = builder.build().toString();

            HttpGet get = new HttpGet(str);

            get.setConfig(requestConfig);

            headers.forEach((key, value) -> {
                if (Objects.nonNull(key) && Objects.nonNull(value)) {
                    get.setHeader(key, value);
                }
            });

            HttpResponse response = httpClient.execute(get);

            StatusLine line = response.getStatusLine();

            if (Objects.nonNull(line) && Objects.equals(HttpStatus.SC_OK, line.getStatusCode())) {
                return EntityUtils.toString(response.getEntity(), "UTF-8");
            }

            throw new RuntimeException(" HTTP HANDLE FAILED ");

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    public String post(String uri, Map<String, Object> parameters) {
        try {
            HttpPost post = new HttpPost(uri);

            post.setConfig(requestConfig);

            List<NameValuePair> pairs = new ArrayList<>();

            parameters.forEach((key, value) -> {
                if (Objects.nonNull(value)) {
                    pairs.add(new BasicNameValuePair(key, value.toString()));
                }
            });

            UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(pairs, "UTF-8");

            post.setEntity(urlEncodedFormEntity);

            HttpResponse response = httpClient.execute(post);

            StatusLine line = response.getStatusLine();

            if (Objects.nonNull(line) && Objects.equals(HttpStatus.SC_OK, line.getStatusCode())) {
                return EntityUtils.toString(response.getEntity(), "UTF-8");
            }

            throw new RuntimeException(" HTTP HANDLE FAILED ");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    public String post(String uri, String json, Map<String, String> headers) {
        try {
            if (StringUtils.isNotEmpty(json)) {

                HttpPost post = new HttpPost(uri);

                post.setConfig(requestConfig);

                StringEntity stringEntity = new StringEntity(json, "UTF-8");

                stringEntity.setContentType("application/json");

                post.setEntity(stringEntity);

                headers.forEach((key, value) -> {
                    if (Objects.nonNull(key) && Objects.nonNull(value)) {
                        post.setHeader(key, value);
                    }
                });

                HttpResponse response = httpClient.execute(post);

                StatusLine line = response.getStatusLine();

                if (Objects.nonNull(line) && Objects.equals(HttpStatus.SC_OK, line.getStatusCode())) {
                    return EntityUtils.toString(response.getEntity(), "UTF-8");
                }
            }

            throw new RuntimeException(" HTTP HANDLE FAILED ");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    public String postForm(String uri, Map<String, String> bodys, Map<String, String> headers) {
        try {
            HttpPost post = new HttpPost(uri);

            headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");

            for (Map.Entry<String, String> e : headers.entrySet()) {
                post.addHeader(e.getKey(), e.getValue());
            }
            if (bodys != null) {
                List<NameValuePair> nameValuePairList = new ArrayList<>();

                for (String key : bodys.keySet()) {
                    nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key)));
                }
                UrlEncodedFormEntity formEntity = null;

                formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8");

                formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
                post.setEntity(formEntity);

                HttpResponse response = httpClient.execute(post);

                StatusLine line = response.getStatusLine();

                if (Objects.nonNull(line) && Objects.equals(HttpStatus.SC_OK, line.getStatusCode())) {
                    return EntityUtils.toString(response.getEntity(), "UTF-8");
                }
            }

            throw new RuntimeException(" HTTP HANDLE FAILED ");
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }

    }

    public void setHttpClient(HttpClient httpClient) {
        this.httpClient = httpClient;
    }

    public void setRequestConfig(RequestConfig requestConfig) {
        this.requestConfig = requestConfig;
    }
}
